package com.qdlc.p2p.biz.util;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.qdlc.p2p.biz.processor.event.NoticeTemplateValueEvent;
import com.qdlc.p2p.common.core.ReturnResult;
import com.qdlc.p2p.common.core.queue.QueueHandlers;
import com.qdlc.p2p.common.core.queue.ValueEvent;
import com.qdlc.p2p.common.core.redis.JedisCacheFactory;
import com.qdlc.p2p.common.util.DateUtil;
import com.qdlc.p2p.common.util.LogFactory;
import com.qdlc.p2p.common.util.RandomUtil;
import com.qdlc.p2p.dal.common.SystemConfigHelper;
import com.qdlc.p2p.dal.common.NoticeTypeHelper.NidType;
import com.qdlc.p2p.dal.common.SystemConfigHelper.Nid;
import com.qdlc.p2p.dal.dto.User;
import com.qdlc.p2p.dal.util.SystemConfigs;

/**
 * 处理验证码功能
 * 1. 发送手机/邮箱验证码
 * 2. 校验验证码
 * @author linya
 */
public class ValidCodeSender {

	private static Logger logger = LogFactory.CODE_SEND_LOGGER;
	
	private static final String CACHE_PREFIX = "valid_code_";
	
	//定义验证码过期时间，默认为30分钟
	private long expireTime = 30;
	
	//定义发送频率时间，默认为60秒
	private long frequencyTime = 1;
	
	//时间单位
	private TimeUnit timeUnit = TimeUnit.MINUTES;
	
	public static ValidCodeSender newInstance(){
		return new ValidCodeSender();
	}
	
	public void setExpireTime(long expireTime) {
		this.expireTime = expireTime;
	}

	public void setFrequencyTime(long frequencyTime) {
		this.frequencyTime = frequencyTime;
	}

	public void setTimeUnit(TimeUnit timeUnit) {
		this.timeUnit = timeUnit;
	}

	/**
	 * 邮箱发送验证码
	 * @param userId
	 * @param email
	 * @param noticeTypeNid
	 */
	public ReturnResult sendCodeByEmail(User user, String email, String noticeTypeNid){
		//生成验证码
		String code = RandomUtil.code();//RandomUtil.getStringRandom(6);
		String logInfo = MessageFormat.format("++++ [绑定邮箱]用户{0},邮箱{1},验证码{2}", user, email, code);
		logger.info(logInfo);
		
		//获取发送参数
		Map<String, Object> sendData = commonSendData();
		sendData.put("email", email);
		sendData.put("code", code);
		
		//发送验证码
		ReturnResult result = send(user, noticeTypeNid, NidType.NOTICE_EMAIL, sendData);
		
		//写入的Redis缓存中
		if(result.isSuccess()){
			putCache(user, code, noticeTypeNid);
		}
		
		return result;
	}
	
	/**
	 * 短信发送验证码
	 * @param userId
	 * @param mobilePhone
	 * @param noticeTypeNid
	 */
	public ReturnResult sendCodeByPhone(User user, String mobilePhone, String noticeTypeNid){
		//生成验证码
		String code = RandomUtil.code();
		
		//获取发送参数
		Map<String, Object> sendData = commonSendData();
		sendData.put("mobilePhone", mobilePhone);
		sendData.put("code", code);
		
		//发送验证码
		ReturnResult result = send(user, noticeTypeNid, NidType.NOTICE_SMS, sendData);
		
		//写入的Redis缓存中
		if(result.isSuccess()){
			putCache(user, code, noticeTypeNid);
		}
		
		return result;
	}
	
	/**
	 * 设置公共的发送数据
	 * @return
	 */
	private Map<String, Object> commonSendData(){
		Map<String, Object> sendData = new HashMap<String, Object>();
		sendData.put("host", SystemConfigHelper.getValue(Nid.WEB_URL));
		sendData.put("web_url", SystemConfigHelper.getValue(Nid.WEB_URL));
		sendData.put("web_name", SystemConfigs.WEB_NAME);
		sendData.put("customer_hotline", SystemConfigHelper.getValue(Nid.CUSTOMER_HOTLINE));
		sendData.put("copyright", SystemConfigHelper.getValue(Nid.COPYRIGHT));
		sendData.put("web_record_number", SystemConfigHelper.getValue(Nid.WEB_RECORD_NUMBER));
		sendData.put("noticeTime", DateUtil.dateStr(DateUtil.getNow(), "MM月dd日 HH时mm分ss秒"));
		sendData.put("vtime", SystemConfigHelper.getIntegerValue(Nid.VERIFY_CODE_TIME));
		return sendData;
	}
	
	/**
	 * 发送验证码，并等待线程返回
	 * @param user
	 * @param noticeTypeNid
	 * @param sendData
	 * @return
	 */
	private ReturnResult send(User user, String noticeTypeNid, NidType nidType, Map<String, Object> sendData){
		
		//检测是否可以发送
		String key = wrapFrequencyKey(user.getUserId(), noticeTypeNid, nidType);
		Boolean checked = JedisCacheFactory.newInstance(Boolean.class).get(key);
		if(checked != null && checked){
			return new ReturnResult("发送频繁,请稍后操作!");
		}
		
		NoticeTemplateValueEvent event = NoticeTemplateValueEvent.newInstance(user, noticeTypeNid, nidType).addSendData(sendData);
		Future<ValueEvent> future = QueueHandlers.submit(event);
		try {
			//等待任务完成
			future.get();
			//设置发送频率时间
			JedisCacheFactory.newInstance(Boolean.class).set(key, true, frequencyTime, timeUnit);
		} catch (Exception e) {
			return new ReturnResult("验证码发送失败!");
		}
		
		return ReturnResult.SUCCESS;
	}
	
	/**
	 * 存放验证码到缓存
	 * @param user
	 * @param code
	 * @param noticeTypeNid
	 */
	private void putCache(User user, String code, String noticeTypeNid){
		String key = wrapKey(user.getUserId(), noticeTypeNid);
		JedisCacheFactory.newInstance(String.class).set(key, code, expireTime, timeUnit);
	}
	
	/**
	 * 校验验证码
	 * @param user
	 * @param code
	 * @param noticeTypeNid
	 * @return
	 */
	public static ReturnResult checkValidCode(User user, String code, String noticeTypeNid){
		//从缓存中获取验证码
		String key = wrapKey(user.getUserId(), noticeTypeNid);
		String cacheCode = JedisCacheFactory.newInstance(String.class).get(key);
		
		if(StringUtils.isEmpty(cacheCode)){
			return new ReturnResult("验证码不存在或已失效,请重新获取!");
		}
		
		if(!cacheCode.equalsIgnoreCase(code)){
			return new ReturnResult("验证码错误!");
		}
		
		//校验成功，删除缓存
		JedisCacheFactory.newInstance(String.class).delete(key);
		
		return ReturnResult.SUCCESS;
	}
	
	
	/**
	 * 包装缓存Key
	 * @param userId
	 * @param noticeTypeNid
	 * @return
	 */
	public static String wrapKey(long userId, String noticeTypeNid){
		return CACHE_PREFIX + userId + "_" + noticeTypeNid;
	}
	
	private static String wrapFrequencyKey(long userId, String noticeTypeNid, NidType nidType){
		return CACHE_PREFIX + "frequency_" + userId + "_" + noticeTypeNid + "_" + nidType.name();
	}
	
}
